package com.dily.study.user.service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dily.scaffold.common.reponse.BaseResponse;
import com.dily.study.user.entity.dto.LoginUser;
import com.dily.study.user.mapper.UserMapper;
import com.dily.study.user.utils.StringRedisUtils;
import com.dily.study.user.entity.User;
import com.dily.study.user.utils.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * Date: 2022-06-10 星期五
 * Time: 11:03
 * Author: Dily_Su
 * Remark:
 */
@Service
public class UserService extends ServiceImpl<UserMapper, User> {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private StringRedisUtils redisUtils;

    /**
     * 登录
     *
     * @param user 用户
     * @return response
     */
    public BaseResponse<?> login(User user) {
        // 用户认证 将user 封装成 AuthenticationToken, AuthenticationManage 用 authenticate 方法去认证
        Authentication authentication = new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword());
        Authentication authenticate = authenticationManager.authenticate(authentication);

        // 如果认证失败，给出提示
        if (Objects.isNull(authenticate))
            throw new RuntimeException("登录失败");

        // 如果认证通过, 生成token, 返回
        LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
        Map<String, String> map = new HashMap<>();
        map.put("token", createToken(loginUser));
        // 将完整用户信息存入redis, username 和 id 作为Key

        String key = "login:" + loginUser.getUser().getUsername() + "(" + loginUser.getUser().getId() + ")";

        redisUtils.set(key, JSON.toJSONString(loginUser));

        return BaseResponse.success(map);
    }

    /**
     * 登出
     *
     * @return response
     */
    public BaseResponse<?> logout() {
        // 获取当前用户
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        Long userId = loginUser.getUser().getId();
        //删除 redis 中 的值
        redisUtils.del("login:" + userId);
        return BaseResponse.success();
    }

    /**
     * 生成Token
     *
     * @param loginUser 登录用户
     * @return token
     */
    public String createToken(LoginUser loginUser) {
        String jwtKey = loginUser.getUser().getId() + "." + JSON.toJSONString(loginUser.getRoles()) + "." + JSON.toJSONString(loginUser.getPermissions());
        return JwtUtil.createJWT(jwtKey);
    }

    /**
     * 解析Token
     *
     * @param token token
     * @return LoginUser
     */
    public LoginUser parseToken(String token) throws Exception {
        String[] jwtArray = JwtUtil.parseJWT(token).getSubject().split("\\.");
        User user = this.getById(jwtArray[0]);
        List<String> roles = JSON.parseArray(jwtArray[1], String.class);
        List<String> permissions = JSON.parseArray(jwtArray[2], String.class);
        return new LoginUser(user, roles, permissions);
    }
}
